/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.elem;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import self.gee.IGraphicElement;
import self.gee.IRectangularElement;
import self.xml.DomUtils;

abstract public class ARectangularHandledElement extends AGraphicElement implements IRectangularElement {
  final static public   String BOUNDS_PROP = "bounds";
  protected Rectangle     fig   = new Rectangle( 10, 10, 80, 80 );
  protected Point[]       handles = new Point[4];

  public ARectangularHandledElement() {
    for ( int cntr = 0; cntr < handles.length; cntr++ ) // consider doing lazy init
      handles[cntr] = new Point();
  }

  protected void resetFrame() {
	// nothing to do.
  }

  public void       setLocation( int x, int y ) {
    layer.beginUpdate();
    fig.setLocation( x, y );
    resetFrame();
    layer.endUpdate();
    layer.setDirty();
  }

  public void       move( Dimension moveBy, MouseEvent e, int dragState ) {
    if ( dragState == IGraphicElement.DS_AFTER_LAST ) {
      layer.setDirty();
      outlineOnly = false;
      return;
    }
    outlineOnly = true;
    layer.beginUpdate();
    fig.x += moveBy.width;
    fig.y += moveBy.height;
    resetFrame();
    layer.endUpdate();
  }

  public void       resize( int x, int y, Point[] handle, MouseEvent e, int dragState ) {
    if ( dragState == IGraphicElement.DS_AFTER_LAST ) {
      layer.setDirty();
      outlineOnly = false;
      return;
    }
    outlineOnly = true;
    Point anchor;
    if ( handle == null )
      anchor = fig.getLocation();
    else
      anchor = getAnchorPoint( handle[0] );
    layer.beginUpdate();
    self.math.geom.RectangleUtils.updateRectangleToTlbr( fig, anchor.x, anchor.y, x, y );
    resetFrame();
    layer.endUpdate();
  }

  public boolean getLineIntersectionToCentre( int xFrom, int yFrom, int[] xyPoints ) {
    double[] xyP = new double[2];
    self.math.geom.RectangleUtils.getRectCentrePointIntersections( fig, xFrom, yFrom, xyP );
    xyPoints[0] = (int)xyP[0];
    xyPoints[1] = (int)xyP[1];
    return true;
  }

  public void       getHandlePoints( java.util.List store ) {
    initHandlePoints();
    for ( int cntr = 0; cntr < handles.length; cntr++ )
      store.add( handles[cntr] );
  }

  public boolean    contains( Point within ) {
    return fig.contains( within );
  }

  public boolean    isWithin( Rectangle within ) {
    return fig.intersects( within );
  }

  // IRectangularElement
  public Rectangle getBounds() {
    return fig;
  }

  public Rectangle  getOverallBounds() {
    return getBounds();
  }

  public void setBounds( Rectangle data ) {
    layer.beginUpdate();
    fig.setBounds( data );
    resetFrame();
    layer.endUpdate();
  }

  // IEditableElement support
  public void       getProperties( Map store ) {
    store.put( BOUNDS_PROP, fig.clone() );
  }

  public void       setProperties( Map data ) {
    fig.setBounds( (Rectangle)data.get(BOUNDS_PROP) );
    layer.setDirty();
    initHandlePoints();
  }

  // IPersistentElement support
  public void readFrom( Node selfRef, HashMap idObjLookUp ) throws DOMException {
    Rectangle[] source = new Rectangle[] { fig };
    String rectAsString = DomUtils.getElementAttribute( selfRef, BOUNDS_PROP );
    self.awt.RectangleUtils.parseRectangle( rectAsString, source );
    resetFrame();
  }

  public void writeTo( Document doc, Element selfRef, HashMap objIdLookup ) throws DOMException {
    DomUtils.setElementAttribute( selfRef, BOUNDS_PROP, self.awt.RectangleUtils.toString(fig) );
  }

  public String toString() {
    return "[" + this.getClass().getName() + "@" + hashCode() +"]" + fig.toString();
  }

  protected void initHandlePoints() {
    handles[0].x = fig.x;
    handles[0].y = fig.y;
    handles[1].x = fig.x + fig.width;
    handles[1].y = fig.y;
    handles[2].x = fig.x + fig.width;
    handles[2].y = fig.y + fig.height;
    handles[3].x = fig.x;
    handles[3].y = fig.y + fig.height;
  }

  private Point getAnchorPoint( Point handleHit ) {
    int cntr;
    for ( cntr = 0; cntr < handles.length; cntr++ ) {
      if ( handles[cntr].equals(handleHit) )
        break;
    }
    int anchorPos = -1;
    switch (cntr) {
      case 0: anchorPos = 2; break;
      case 1: anchorPos = 3; break;
      case 2: anchorPos = 0; break;
      case 3: anchorPos = 1; break;
    }
    return handles[anchorPos];
  }

  public void UT_dumpHandlePoints() {
    for ( int cntr = 0; cntr < 4; cntr++ ) {
      System.out.println("\thp[" + cntr + "] = " + handles[cntr] );
    }
  }
}
